#pragma once
#include <iostream>
#include "Socket.hpp"
#include "Epoll.hpp"

class EpollServer
{
    static const int DEFAULT_PORT = 8080;
    static const int default_timeout = -1;
    static const int gum = 10;

public:
    EpollServer(int server_port = DEFAULT_PORT) : _events_num(gum), _timeout(default_timeout),_server_port(server_port)
    {
        _events = new epoll_event[_events_num];
        // 引入网络流
        _listen_fd = Socket::Sock();
        std::cout << _listen_fd << std::endl;
        Socket::Bind(_listen_fd, _server_port);
        Socket::Listen(_listen_fd);
        // 创建Epoll,并吧listent文件描述符加入Epoll中控制
        _epfd = Epoll::CreateEpoll();
        if (!Epoll::CtlEpoll(_epfd, EPOLL_CTL_ADD, _listen_fd, EPOLLIN))
            exit(6);
    }
    void Start()
    {
        std::cout << "服务器启动" << std::endl;
        while(true)
        {
            LoopOnce();
        }
    }
    ~EpollServer()
    {
        if (_events)
        {
            delete[] _events;
            _events = nullptr;
        }
    }

private:
    EpollServer(const EpollServer &epollServer) = delete;
    void LoopOnce()
    {
        std::cout << "判断有无事件到来" << std::endl;

        int num = Epoll::WaitEpoll(_epfd, _events, _events_num, _timeout);
        switch (num)
        {
        case 0:
            std::cout << "timeout" << std::endl;
            break;
        case -1:
            std::cerr << "epoll_wait error" << std::endl;
            break;
        default:
            HanderEvent(num);
            break;
        }
    }
    void HanderEvent(int num)
    {
        std::cout << "有事件到来了" << std::endl;
        for (int i = 0; i < num; i++)
        {
            switch (_events[i].events)
            {
            case EPOLLIN:
                if (_events[i].data.fd == _listen_fd)
                {
                    ServerAccept();
                }
                else
                {
                    Receive(_events[i].data.fd);
                }
                break;
            case EPOLLOUT:
                break;
            // ERROR
            default:
                break;
            }
        }
    }
    void ServerAccept()
    {
        std::cout << "get a new link" << std::endl;
        std::string client_ip;
        uint16_t client_port;
        int accept_errno;
        int sock = Socket::Accept(_listen_fd, &client_ip, &client_port, &accept_errno);
        if(sock < 0)
        {
            std::cout << "accept errno" << std::endl;
            return;
        }
        // 加入epoll中管理
        Epoll::CtlEpoll(_epfd, EPOLL_CTL_ADD, sock, EPOLLIN);
    }
    void Receive(int sock)
    {
        char buffer[1024];
        int num = recv(sock, buffer, sizeof(buffer) - 1, 0);
        switch (num)
        {
        case -1:
            std::cout << "recv errno" << std::endl;
            Epoll::CtlEpoll(_epfd, EPOLL_CTL_DEL, sock, EPOLLIN);
            close(sock);
            break;
        case 0:
            std::cout << "client close" << std::endl;

            Epoll::CtlEpoll(_epfd, EPOLL_CTL_DEL, sock, EPOLLIN);
            close(sock);
            break;
        default:
            buffer[num] = 0;
            std::cout << "client:" << buffer << std::endl;
            break;
        }
    }

private:
    int _epfd;
    int _listen_fd;
    int _server_port;
    epoll_event *_events;
    int _events_num;
    int _timeout;
};